﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Input;
using Amazon.SimpleDB;
using Amazon.SimpleDB.Model;

namespace SimpleDbBrowser.ViewModel
{
    /// <summary>
    /// The view model responsible for exposing the DeleteDomain command.
    /// </summary>
    public sealed class DeleteDomainViewModel : ViewModelBase
    {
        private readonly AmazonSimpleDB db;
        private string selectedDomain;
        private bool deleteConfirmed = true;

        /// <summary>
        /// Initializes a new instance of the DeleteDomainViewModel class.
        /// </summary>
        /// <param name="database">
        /// The simpledb that this viewmodel will work with.
        /// </param>
        public DeleteDomainViewModel(AmazonSimpleDB database)
        {
            Debug.WriteLine("Creating DeleteDomainViewModel");

            if (database == null) throw new ArgumentNullException("database");
            this.db = database;

            this.DisplayName = "Delete the selected domain";

            this.DeleteDomain = new RelayCommand(this.OnDeleteDomain, this.CanDeleteDomain);

        }

        /// <summary>
        /// Gets the DeleteDomain command.
        /// </summary>
        /// <remarks>
        /// If this command is executed while DeletionConfirmed is false, 
        /// it will set DeletionConfirmed to true and return without deleting
        /// the domain.
        /// </remarks>
        public ICommand DeleteDomain { get; private set; }

        /// <summary>
        /// The domain that will be deleted by the DeleteDomain command.
        /// </summary>
        public string SelectedDomain
        {
            get { return this.selectedDomain; }

            set
            {
                if (this.selectedDomain == value) return;

                this.selectedDomain = value;
                this.OnPropertyChanged("SelectedDomain");
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the domain should be 
        /// deleted when the DeleteDomain command is run.
        /// </summary>
        /// <remarks>
        /// This property exists to facilitate the use of a confirmation dialog
        /// when delete is clicked.  It always defaults to true.
        /// </remarks>
        public bool DeletionConfirmed
        {
            get { return this.deleteConfirmed; }
            set
            {
                if (this.deleteConfirmed == value) return;

                this.deleteConfirmed = value;
                this.OnPropertyChanged("DeletionConfirmed");
            }
        }

        /// <summary>
        /// Fires when a domain has been deleted via this viewmodel.
        /// </summary>
        public event EventHandler DomainDeleted;

        /// <summary>
        /// Executes the DeleteDomain command.
        /// </summary>
        /// <param name="obj">
        /// The command parameter.  This is not used.
        /// </param>
        /// <remarks>
        /// If the DeletionConfirmed property is false, this method will 
        /// set it to true and return immediately, without executing the domain
        /// deletion.
        /// </remarks>
        private void OnDeleteDomain(object obj)
        {
            if(!this.DeletionConfirmed)
            {
                Debug.WriteLine("Domain deletion cancelled.");
                this.DeletionConfirmed = true;
                return;
            }

            var dmnName = this.SelectedDomain;
            var worker = new BackgroundWorker();
            worker.DoWork += (s, o) =>
                             {
                                 var req = new DeleteDomainRequest().WithDomainName(dmnName);
                                 var resp = this.db.DeleteDomain(req);
                             };

            worker.RunWorkerCompleted += (s, o) => this.OnDomainDeleted(EventArgs.Empty);

            worker.RunWorkerAsync();
        }

        /// <summary>
        /// Determines whether the DeleteDomain command can be executed.
        /// </summary>
        /// <param name="o">
        /// The command parameter.  This is not used.
        /// </param>
        /// <returns>
        /// True if the domain can be deleted, otherwise false.
        /// </returns>
        private bool CanDeleteDomain(object o)
        {
            return !string.IsNullOrWhiteSpace(this.SelectedDomain);
        }

        /// <summary>
        /// Perform actions that must occur when a domain has been deleted.
        /// </summary>
        /// <param name="args">
        /// Arguments for the DomainDeleted event.
        /// </param>
        private void OnDomainDeleted(EventArgs args)
        {
            var tmp = this.DomainDeleted;
            if (tmp != null)
            {
                tmp(this, args);
            }

            return;
        }
    }
}